package com.sdy.usercenter.web.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sdy.auth.api.model.UserInfo;
import com.sdy.auth.client.service.SsoService;
import com.sdy.common.constant.Constants;
import com.sdy.common.model.BizException;
import com.sdy.common.model.Response;
import com.sdy.common.utils.Assert;
import com.sdy.common.utils.DateUtil;
import com.sdy.common.utils.EncodeUtil;
import com.sdy.common.utils.IdCardUtil;
import com.sdy.common.utils.MapUtil;
import com.sdy.common.utils.OsPathUtil;
import com.sdy.common.utils.RandomUtil;
import com.sdy.common.utils.StringUtil;
import com.sdy.mq.service.MqProducerService;
import com.sdy.mvc.controller.BaseController;
import com.sdy.mvc.utils.HttpUtil;
import com.sdy.usercenter.biz.constants.MqConstants;
import com.sdy.usercenter.biz.model.SysDept;
import com.sdy.usercenter.biz.model.SysLog;
import com.sdy.usercenter.biz.model.SysRole;
import com.sdy.usercenter.biz.model.SysUser;
import com.sdy.usercenter.biz.model.SysUserApp;
import com.sdy.usercenter.biz.model.SysUserDept;
import com.sdy.usercenter.biz.model.SysUserRole;
import com.sdy.usercenter.biz.service.SysDeptService;
import com.sdy.usercenter.biz.service.SysRoleService;
import com.sdy.usercenter.biz.service.SysUserAppService;
import com.sdy.usercenter.biz.service.SysUserDeptService;
import com.sdy.usercenter.biz.service.SysUserRoleService;
import com.sdy.usercenter.biz.service.SysUserService;
import com.sdy.usercenter.web.vo.ActiveUserVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户基础信息表 前端控制器
 * </p>
 *
 * @author zzq
 * @since 2019-06-14
 */
@Slf4j
@RestController
@RequestMapping("/sysUser")
public class SysUserController extends BaseController {
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysUserDeptService sysUserDeptService;
    @Autowired
    private SysDeptService sysDeptService;
    @Autowired
    private SysUserRoleService sysUserRoleService;
    @Autowired
    private SysRoleService sysRoleService;
    @Autowired
    private SsoService ssoService;
    @Autowired
    private MqProducerService mqProducerService;
    @Autowired
    private SysUserAppService sysUserAppService;
    
    @GetMapping("/get")
    public Response get(Integer id) {
        SysUser user = sysUserService.getById(id);
        user.setPassword(null);
        user.setImgUrl(user.getImgUrl());
        List<SysUserDept> list = sysUserDeptService.listByExample(new SysUserDept().setAdmin(2).setUserId(user.getId()));
        if (!list.isEmpty()) {
            user.setDeptId(list.get(0).getDeptId());
            SysDept sysDept = sysDeptService.getById(user.getDeptId());
            if (sysDept != null) {
                user.setDeptName(sysDept.getAbbreviation());
                user.setDeptId(sysDept.getId());
            }
        }
        return Response.success(user);
    }

    /**
     * 获取账号信息
     * @param id 用户id
     */
    @GetMapping("/accountInfo")
    public Response accountInfo(Integer id) throws BizException {
        ActiveUserVO vo = new ActiveUserVO();
        SysUser user = sysUserService.getById(id);
        Assert.isNull(user, "用户不存在");
        vo.setAllowIp(user.getAllowIp())
                .setEffectTime(user.getEffectTime())
                .setExpireTime(user.getExpireTime())
                .setLoginName(user.getSimpleLoginName())
                .setUserId(id)
                .setExpireType(user.getEffectTime() != null && user.getExpireTime() == null ? 1 : 2);
        return Response.success(vo);
    }

    /**
     * 获取用户角色信息
     * @param id 用户id
     */
    @GetMapping("/roleList")
    public Response roleList(Integer id) throws BizException {
        Assert.isNull(id, "用户ID不能为空");
        return Response.success(sysUserService.listUserRole(id, false));
    }

    /**
     * 更新用户角色
     */
    @PostMapping("/updateUserRole")
    public Response updateUserRole(Integer userId, @RequestBody List<Integer> roleIdList) throws BizException {
        Assert.isNull(userId, "用户ID不能为空");
        sysUserService.updateUserRole(userId, roleIdList);
        return Response.success();
    }

    /**
     * 获取账号信息
     */
    @PostMapping("/updateAccountInfo")
    public Response updateAccountInfo(HttpServletRequest request, @RequestBody ActiveUserVO accountInfo) throws Exception {
        Integer userId = accountInfo.getUserId();
        SysUser oldUser = sysUserService.getById(userId);
        Assert.isNull(userId, "用户ID为空");
        Assert.isNull(accountInfo.getEffectTime(), "生效时间为空");
        Assert.isBlank(accountInfo.getLoginName(), "用户登录名为空");
        Assert.isTrue(accountInfo.getLoginName().contains("."), "登录名不能包含.字符");
        // 校验登陆名唯一性
        boolean unique = sysUserService.checkUsernameUnique(accountInfo.getLoginName(), userId, oldUser.getDeptId());
        Assert.isTrue(!unique, "登录名 \"" + accountInfo.getLoginName() + "\" 已存在，请返回修改");
        
        SysUser vo = new SysUser()
                .setId(accountInfo.getUserId())
                .setSimpleLoginName(accountInfo.getLoginName())
                .setLoginName(accountInfo.getLoginName() + sysUserService.getUserDeptSuffix(userId, oldUser.getDeptId()))
                .setEffectTime(accountInfo.getEffectTime())
                .setAllowIp(accountInfo.getAllowIp());
        if (accountInfo.getExpireType().equals(2)) {
            // 限时
            vo.setExpireTime(accountInfo.getExpireTime());
        } else {
            vo.setExpireTime(null);
        }

        sysUserService.updateWithNullTime(vo);

        // 日志消息
        UserInfo opUserInfo = ssoService.getUserInfo(request);
        mqProducerService.send(MqConstants.Tags.TAG_OP_LOG,
                SysLog.LogType.EDIT_USER.getTypeS().concat(MqConstants.SEP_TOKEN)
                        .concat(opUserInfo.getUserId().toString()).concat(MqConstants.SEP_TOKEN)
                        .concat(DateUtil.formatTime(new Date())).concat(MqConstants.SEP_TOKEN)
                        .concat(HttpUtil.getIpAddr(request)).concat(MqConstants.SEP_TOKEN)
                        .concat(opUserInfo.getUserName() + " 编辑用户信息：" + vo.getName() + " [" + oldUser.getId() + "]")
        );
        return Response.success();
    }

    /**
     * 用户开户
     */
    @PostMapping("/activateUser")
    public Response activateUser(HttpServletRequest request, @RequestBody ActiveUserVO activeUserVO) throws Exception {
        Assert.isNull(activeUserVO.getUserId(), "用户ID为空");
        Assert.isNull(activeUserVO.getEffectTime(), "生效时间为空");
        Assert.isBlank(activeUserVO.getLoginName(), "用户登录名为空");
        Assert.isTrue(activeUserVO.getLoginName().contains("."), "登录名不能包含.字符");
        // 校验登陆名唯一性
        boolean unique = sysUserService.checkUsernameUnique(activeUserVO.getLoginName(), activeUserVO.getUserId(), null);
        Assert.isTrue(!unique, "登录名 \"" + activeUserVO.getLoginName() + "\" 已存在，请返回修改");
        
        SysUser vo = new SysUser()
                .setId(activeUserVO.getUserId())
                .setSimpleLoginName(activeUserVO.getLoginName())
                .setLoginName(activeUserVO.getLoginName() + sysUserService.getUserDeptSuffix(activeUserVO.getUserId(), null))
                .setEffectTime(activeUserVO.getEffectTime())
                .setAllowIp(activeUserVO.getAllowIp());
        if (activeUserVO.getExpireType().equals(2)) {
            // 限时
            vo.setExpireTime(activeUserVO.getExpireTime());
        } else {
            vo.setExpireTime(null);
        }
        String password = RandomUtil.produceNumber(6);
        vo.setPassword(EncodeUtil.sha256(password));
        sysUserService.openAccount(vo, ssoService.getUserInfo(request), HttpUtil.getIpAddr(request));
        // 发送开户短信
        return Response.success(password);
    }

    /**
     * 分页数据
     * @param request
     * @param page [current, size]
     * @return
     */
    @GetMapping("/pageData")
    public Response pageData(HttpServletRequest request, Page<SysUser> page, String loginName, String name, String phone, Integer state) {
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.likeRight(StringUtil.isNotBlank(loginName), SysUser::getLoginName, loginName);
        wrapper.like(StringUtil.isNotBlank(name), SysUser::getName, name);
        wrapper.eq(StringUtil.isNotBlank(phone), SysUser::getPhone, phone);
        wrapper.eq(state != null && state != 3, SysUser::getState, state);
        wrapper.isNull(state != null && state == 3, SysUser::getEffectTime);
        wrapper.orderByDesc(SysUser::getId);

        IPage<SysUser> result = sysUserService.page(page, wrapper);
        
        // 查询用户所在的部门
        if (!result.getRecords().isEmpty()) {
            List<Integer> userIdList = result.getRecords().stream().map(SysUser::getId).collect(Collectors.toList());
            List<SysUserDept> userDeptList = sysUserDeptService.lambdaQuery().in(SysUserDept::getUserId, userIdList).eq(SysUserDept::getAdmin, 2).list();
            if (!userDeptList.isEmpty()) {
                Collection<SysDept> deptList = sysDeptService.listByIds(userDeptList.stream().map(SysUserDept::getDeptId).collect(Collectors.toList()));
                Map<Integer, Integer> userDeptMap = new HashMap<>();
                Map<Integer, SysDept> deptMap = new HashMap<>();
                userDeptList.forEach(item -> userDeptMap.put(item.getUserId(), item.getDeptId()));
                deptList.forEach(item -> deptMap.put(item.getId(), item));
                result.getRecords().forEach(item -> {
                    Integer deptId = userDeptMap.get(item.getId());
                    if (deptId != null) {
                        SysDept dept = deptMap.get(deptId);
                        if (dept != null) {
                            item.setDeptName(dept.getAbbreviation());
                        }
                    }
                });
            }
            // 查询用户角色
            List<SysUserRole> roleUserlist = sysUserRoleService.lambdaQuery().in(SysUserRole::getUserId, userIdList).list();
            if (!roleUserlist.isEmpty()) {
                Collection<SysRole> roleList = sysRoleService.listByIds(roleUserlist.stream().map(SysUserRole::getRoleId).collect(Collectors.toList()));
                Map<Integer, List<SysUserRole>> roleUserMap = MapUtil.collectionToMapList(roleUserlist, SysUserRole::getUserId);
                Map<Integer, SysRole> roleMap = MapUtil.collectionToMap(roleList, SysRole::getId);
                result.getRecords().forEach(item -> {
                    List<SysUserRole> urList = roleUserMap.getOrDefault(item.getId(), Collections.emptyList());
                    item.setRoleList(urList.stream().filter(ur -> roleMap.containsKey(ur.getRoleId())).map(ur -> roleMap.get(ur.getRoleId())).collect(Collectors.toList()));
                });
            }
        }
        return Response.success(result);
    }

    /**
     * 保存数据
     * @param
     * @return
     */
    @PostMapping("/save")
    public Response save(HttpServletRequest request, @RequestBody SysUser sysUser) throws Exception {
        if (StringUtil.isBlank(sysUser.getImgUrl())) {
            sysUser.setImgUrl(null);
        }
        Assert.isTrue(!sysUser.getPhone().matches(Constants.REGEX_PHONE), "手机号格式错误");
        Assert.isTrue(!IdCardUtil.IDCardValidate(sysUser.getIdCard()).equals("true"), "身份证格式错误");
        sysUserService.saveUser(sysUser.setCreateTime(new Date()));
        UserInfo opUserInfo = ssoService.getUserInfo(request);
        mqProducerService.send(MqConstants.Tags.TAG_OP_LOG,
                SysLog.LogType.ADD_USER.getTypeS().concat(MqConstants.SEP_TOKEN)
                        .concat(opUserInfo.getUserId().toString()).concat(MqConstants.SEP_TOKEN)
                        .concat(DateUtil.formatTime(new Date())).concat(MqConstants.SEP_TOKEN)
                        .concat(HttpUtil.getIpAddr(request)).concat(MqConstants.SEP_TOKEN)
                        .concat(opUserInfo.getUserName() + " 新增用户：" + sysUser.getName() + " [" + sysUser.getId() + "]")
        );
        return Response.success(sysUser.getId());
    }

    /**
     * 更新数据
     * @param
     * @return
     */
    @PostMapping("/update")
    public Response update(HttpServletRequest request, @RequestBody SysUser user) throws Exception {
        SysUser vo = new SysUser();
        Integer userId = user.getId();
        SysUser oldUser = sysUserService.getById(userId);
        
        if (StringUtil.isBlank(user.getImgUrl())) {
            user.setImgUrl(null);
        }

        Assert.isNull(userId, "用户ID为空");
        Assert.isNull(user.getDeptId(), "所属组织为空");
        Assert.isTrue(!user.getPhone().matches(Constants.REGEX_PHONE), "手机号格式错误");
        Assert.isTrue(!IdCardUtil.IDCardValidate(user.getIdCard()).equals("true"), "身份证格式错误");

        vo.setId(userId)
                .setName(user.getName())
                .setPhone(user.getPhone())
                .setIdCard(user.getIdCard())
                .setGender(user.getGender())
                .setMail(user.getMail())
                .setProfile(user.getProfile() == null ? "" : user.getProfile())
                .setImgUrl(OsPathUtil.convertToUnix(user.getImgUrl()))
                .setDeptId(user.getDeptId());
        sysUserService.updateUser(vo);

        // 日志消息
        UserInfo opUserInfo = ssoService.getUserInfo(request);
        mqProducerService.send(MqConstants.Tags.TAG_OP_LOG,
                SysLog.LogType.EDIT_USER.getTypeS().concat(MqConstants.SEP_TOKEN)
                        .concat(opUserInfo.getUserId().toString()).concat(MqConstants.SEP_TOKEN)
                        .concat(DateUtil.formatTime(new Date())).concat(MqConstants.SEP_TOKEN)
                        .concat(HttpUtil.getIpAddr(request)).concat(MqConstants.SEP_TOKEN)
                        .concat(opUserInfo.getUserName() + " 编辑用户信息：" + vo.getName() + " [" + oldUser.getId() + "]")
        );
        return Response.success();
    }

    /**
     * 删除数据
     */
    @GetMapping("/delete")
    public Response delete(Integer id) {
        sysUserService.removeById(id);
        sysUserDeptService.remove(new LambdaQueryWrapper<SysUserDept>().eq(SysUserDept::getUserId, id));
        sysUserRoleService.remove(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, id));
        sysUserAppService.remove(new LambdaQueryWrapper<SysUserApp>().eq(SysUserApp::getUserId, id));
        return Response.success();
    }

    /**
     * 禁用用户
     */
    @GetMapping("/disableUser")
    public Response disableUser(Integer id) {
        boolean r = sysUserService.lambdaUpdate().eq(SysUser::getId, id).set(SysUser::getState, 2).update();
        if (!r) {
            return Response.error("禁用失败！");
        }
        return Response.success();
    }

    /**
     * 启用用户
     */
    @GetMapping("/enableUser")
    public Response enableUser(Integer id) {
        boolean r = sysUserService.lambdaUpdate().eq(SysUser::getId, id).set(SysUser::getState, 1).update();
        if (!r) {
            return Response.error("启用失败！");
        }
        return Response.success();
    }

    /**
     * 删除数据
     */
    @PostMapping("/deleteBatch")
    public Response deleteBatch(@RequestBody List<Integer> id) {
        if (id != null && !id.isEmpty()) {
            sysUserService.removeByIds(id);
            sysUserDeptService.remove(new LambdaQueryWrapper<SysUserDept>().in(SysUserDept::getUserId, id));
            sysUserRoleService.remove(new LambdaQueryWrapper<SysUserRole>().in(SysUserRole::getUserId, id));
            sysUserAppService.remove(new LambdaQueryWrapper<SysUserApp>().in(SysUserApp::getUserId, id));
        }
        return Response.success();
    }
    
    @PostMapping("/resetPassword")
    public Response resetPassword(HttpServletRequest request, Integer userId, String password) throws Exception {
        Assert.isNull(userId, "用户id不能为空");
        Assert.isBlank(password, "新密码不能为空");
        sysUserService.modifyPassword(userId, password);
        return Response.success();
    }
}
